package wxdb.tx;

import wxdb.record.RecordFormatter;
import wxdb.storage.Page;
import wxdb.storage.StorageMgr;

public class Transaction {
	static StorageMgr sm = new StorageMgr();
	
	public static int getPageCount(int dbid){
		return sm.getPageCount(dbid);
	}
	
	public static int getInt(int dbid, int pid, int offset){
		byte content[] = getPage(dbid, pid).getContent();
		int intSize = getIntSize();
		byte ivalByte[] = new byte[intSize];
		for(int i=0; i<intSize; ++i){
			ivalByte[i] = content[offset];
			++offset;
		}
		return iByte2Int(ivalByte);
	}
	
	public static String getString(int dbid, int pid, int offset){
		byte content[] = getPage(dbid, pid).getContent();	
		int intSize = getIntSize();
		byte ivalByte[] = new byte[intSize];
		for(int i=0; i<intSize; ++i){
			ivalByte[i] = content[offset];
			++offset;
		}
		
		int len = iByte2Int(ivalByte);			//get the string's length
		if(len == 0)
			return "";
		byte svalByte[] = new byte[len];
		for(int i=0; i<len; ++i){
			svalByte[i] = content[offset];
			++offset;
		}
		return sByte2String(svalByte);
	}
	
	public static void setInt(int dbid, int pid, int offset, int ival){
		byte b[] = int2iByte(ival);
		byte content[] = getPage(dbid, pid).getContent();
		int intSize = getIntSize();
		for(int i=0; i<intSize; ++i){
			content[offset] = b[i];
			++offset;
		}
		writeContent(dbid, pid, content);
	}
	
	public static void setString(int dbid, int pid, int offset, String sval, int len){
		byte[] getByte = String2sByte(sval);
		byte[] sByte;
		int getLen = getByte.length;
		if(getLen > len){					//test if field length exceeds the boundry(len)
			sByte = new byte[len];
			for(int i=0; i<len; ++i){
				sByte[i] = getByte[i];
			}
		}
		else{
			sByte = getByte;
			len = getLen;
		}
		byte iByte[] = int2iByte(len);		//the leading int, indicating the length of the string
		int intSize = getIntSize();
		
		byte content[] = getPage(dbid, pid).getContent();
		for(int i=0; i<intSize; ++i){
			content[offset] = iByte[i];
			++offset;
		}
		for(int i=0; i<len; ++i){
			content[offset] = sByte[i];
			++offset;
		}
		writeContent(dbid, pid, content);
		
	}
	
	public static int getIntSize(){
		return Integer.SIZE/Byte.SIZE;
	}
	
	public static byte[] int2iByte(int ival){
		int intSize = getIntSize();
		byte b[] = new byte[intSize];
		for(int i=0; i<intSize; ++i){
			b[i] = (byte)(ival>>i*8);
		}
		return b;
	}
	
	public static int iByte2Int(byte[] b){
		int ival = 0;
		int intSize = getIntSize();
		for(int i=0; i<intSize; ++i){
			ival = ival | (int)(b[i]<<i*8);
		}
		return ival;
	}
	
	public static byte[] String2sByte(String str){
		return str.getBytes();
	}
	
	public static String sByte2String(byte[] b){
		return new String(b);
	}
	
	private static Page getPage(int dbid, int pid){
		String key = String.valueOf(dbid) + ";" + String.valueOf(pid);
		Page pg = sm.readBufPage(key);
		return pg;
	}
	
	private static void writeContent(int dbid, int pid, byte[] content){
		String key = String.valueOf(dbid) + ";" + String.valueOf(pid);
		sm.writeBufPage(content, key);
	}
	
	public static int append(int dbid, PageFormatter pf){
		int pid = sm.allocPage(dbid);
		Page pg = getPage(dbid, pid);
		pf.format(pg);
		return pid;
		
	}
}
